/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @file nfcee_manager.c
 * @brief NFCEE管理模块实现
 */
#include "nci_data.h"
#include "nci_feature.h"
#include "nci_nfcee.h"
#include "nci_module.h"
#include "nci_task.h"
#include "nfa_ee.h"
#include "nfc_log_api.h"
#include "nfa_ee.h"
#include "ee_int.h"
#include "nci_rf.h"
#include "nfc_config_api.h"

#if IS_FEATURE_ON(NCI_FEATURE_EE)

#if IS_FEATURE_ON(NCI_FEATURE_EE_T4T)
extern tNCI_EXTERN_EE g_t4tee;
#endif // IS_FEATURE_ON(NCI_FEATURE_EE_T4T)

typedef enum {
    NCI_EE_MODULE_DISABLED    = 0x00,
    NCI_EE_MODULE_ENABLING    = 0x01,
    NCI_EE_MODULE_ENABLE_DONE = 0x02,
    NCI_EE_MODULE_DISABLING   = 0x03,
    NCI_EE_MODULE_RECOVERING  = 0x04,
} tNCI_EE_SM_STATE;

typedef struct {
    tNCI_NFCEE nfcees[NCI_MAX_NFCEE_SIZE];
    tNCI_EE_CBACK p_em_cbacks[NCI_MAX_NFCEE_CBACKS];
    tNCI_EE_SM_STATE em_state;
    uint8_t cur_ee_num;
    uint8_t em_cfged;
    uint8_t em_cfg_sts;
    uint8_t route_block_control;
    uint16_t max_aid_rt_size;
    uint16_t cur_aid_rt_size;
    uint16_t max_rt_size;
#if IS_FEATURE_ON(NCI_FEATURE_EE_DH)
    bool secure_nfc_enabled;
#endif // IS_FEATURE_ON(NCI_FEATURE_EE_DH)
} tNCI_EE_MODULE;

// EE模块存放路由表所使用的优先级队列的优先级，高8位决定路由类型的先后顺序，低8位为EE的先后顺序
#define ROUTE_PRIORITY_AID          0x0000
#define ROUTE_PRIORITY_EMPTY_AID    0x0100
#define ROUTE_PRIORITY_APDU_PATTERN 0x0200
#define ROUTE_PRIORITY_SYS_CODE     0x0300
#define ROUTE_PRIORITY_PROTOCOL     0x0400
#define ROUTE_PRIORITY_TECH_A       0x0500
#define ROUTE_PRIORITY_TECH_B       0x0600
#define ROUTE_PRIORITY_TECH_F       0x0700

static tNCI_EE_MODULE s_ee_mod;
static tMUTEX s_em_lock = MUTEX_INIT_VAL("em");

#if IS_FEATURE_ON(NCI_FEATURE_ROUTING)
static tPRIORITY_QUEUE s_routing_table;
#endif // IS_FEATURE_ON(NCI_FEATURE_ROUTING)

static tNCI_EXTERN_EE* s_ext_ee[] = {
#if IS_FEATURE_ON(NCI_FEATURE_EE_T4T)
    &g_t4tee,
#endif // IS_FEATURE_ON(NCI_FEATURE_EE_T4T)
};

#define GET_EM_LOCK_OR_RETURN(ret) \
    if (osi_mutex_lock(&s_em_lock) != NFC_STATUS_OK) { \
        NFCLOG_E("GET_EM_LOCK_OR_RETURN failed"); \
        return ret; \
    }

#define GET_EM_LOCK() GET_EM_LOCK_OR_RETURN(NCI_STATUS_EXT_GET_LOCK_FAILED)

#define RELEASE_EM_LOCK() \
    if (osi_mutex_unlock(&s_em_lock) != NFC_STATUS_OK) { \
        NFCLOG_E("RELEASE_EM_LOCK failed"); \
    }

/**
 * @brief EE模块内部通过ID获取EE, 不包含DH
 */
static tNCI_NFCEE* get_ee_by_id(uint8_t id) {
    tNCI_NFCEE* ret = NULL;
    GET_EM_LOCK_OR_RETURN(ret);
    for (int i = 0; i < s_ee_mod.cur_ee_num; i++) {
        if (s_ee_mod.nfcees[i].nfcee_id == id) {
            ret = &s_ee_mod.nfcees[i];
            break;
        }
    }
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief EE模块内部更新对应EE的Discovery Req参数
 *
 * @param id 目标EE id
 * @param mode 需要更新的tech模式
 * @param protocol 需要更新的协议
 *
 * @return 更新成功返回true，失败返回false
 */
static bool update_ee_discovery_req(uint8_t id, tNCI_RF_TECH_MODE mode, tNCI_RF_PROTOCOL protocol) {
    NFCLOG_D("ee:0x%X, mode:0x%X, protocol:0x%X", id, mode, protocol);
    tNCI_NFCEE* ee = get_ee_by_id(id);
    bool ret = true;
    if (!ee) {
        NFCLOG_W("invalid ee:0x%X", id);
        ret = false;
    } else {
        GET_EM_LOCK_OR_RETURN(false);
        switch (mode) {
            case NCI_RF_TECH_A_PASSIVE_LISTEN_MODE:
                ee->la_protocol = protocol;
                break;
            case NCI_RF_TECH_B_PASSIVE_LISTEN_MODE:
                ee->lb_protocol = protocol;
                break;
            case NCI_RF_TECH_F_PASSIVE_LISTEN_MODE:
                ee->lf_protocol = protocol;
                break;
            default:
                NFCLOG_W("not support mode:%d", mode);
                ret = false;
                break;
        }
        RELEASE_EM_LOCK();
    }
    if (ret) {
        NFCLOG_I("NFCEE: 0x%X tech mode: %d discovery request change to %d", id, mode, protocol);
    }
    return ret;
}

/**
 * @brief 统一管理外部注册的回调，收到EE模块事件后，回调数据
 */
static void report_em_event(tNCI_EE_EVT event, tNCI_EE_EVT_DATA* p_data) {
    NFCLOG_D("event: %d", event);
    for (int i = 0; i < NCI_MAX_NFCEE_CBACKS; i++) {
        tNCI_EE_CBACK cb = s_ee_mod.p_em_cbacks[i];
        if (cb != NULL) {
            (*cb)(event, p_data);
        }
    }
}

/**
 * @brief 检查状态机的状态是否是输入的期望值
 */
static bool check_em_state_unlock(tNCI_EE_SM_STATE expect) {
    bool ret = (s_ee_mod.em_state == expect);
    if (!ret) {
        NFCLOG_E("em_state:%d is not %d", s_ee_mod.em_state, expect);
    }
    return ret;
}

/**
 * @brief 检查输入的EE是不是处于enabled状态
 */
static bool check_ee_enabled_unlock(uint8_t ee_id) {
    if (ee_id == NCI_DH_NFCEE_ID && EE_IS_SUPPORT_DH) {
        return true;
    }
    tNCI_NFCEE* ee = get_ee_by_id(ee_id);
    if (!ee) {
        NFCLOG_E("invalid ee:0x%X", ee_id);
        return false;
    }
    if (ee->status != NCI_NFCEE_ENABLED) {
        NFCLOG_E("ee:0x%02X is not enable: %d", ee_id, ee->status);
        return false;
    }
    return true;
}

/**
 * @brief 使能不支持hci的NFCEE，支持hci的NFCEE交由hci模块使能
 */
static void enable_ee_unsupported_hci() {
    for (uint8_t i = 0; i < s_ee_mod.cur_ee_num; ++i) {
        tNCI_NFCEE *nfcee = &s_ee_mod.nfcees[i];
        // 尝试使能不支持hci的NFCEE，支持hci的NFCEE交由hci模块使能
        if (nfcee->status == NCI_NFCEE_DISABLED && nfcee->num_of_protocol != 0) {
            NFCLOG_I("try enable nfcee: 0x%02X", nfcee->nfcee_id);
            tNCI_STATUS ms_ret = nci_nfcee_mode_set(nfcee->nfcee_id, NCI_NFCEE_MODE_ENABLE);
            if (ms_ret == NCI_STATUS_OK) {
                nfcee->status = NCI_NFCEE_ENABLED;
            } else if (ms_ret == NCI_STATUS_NFCEE_TRANSMISSION_ERROR) {
                nfcee->status = NCI_NFCEE_UNRESPONSIVE;
            } else {
                NFCLOG_W("enable nfcee 0x%02X failed, ms_ret=%d", nfcee->nfcee_id, ms_ret);
            }
        }
    }
}

/**
 * @brief EE异常后，重新发现并恢复EE
 */
static bool recover_ee() {
    tNCI_STATUS ret = NCI_STATUS_OK;
    NFCLOG_W("recovering ee.")
    GET_EM_LOCK_OR_RETURN(false);
    s_ee_mod.em_state = NCI_EE_MODULE_RECOVERING;
    ret = nci_nfcee_discover(s_ee_mod.nfcees, &s_ee_mod.cur_ee_num);
    if (ret == NCI_STATUS_OK) {
        NFCLOG_I("found nfcee count: %d", s_ee_mod.cur_ee_num);
        s_ee_mod.em_state = NCI_EE_MODULE_ENABLE_DONE;
    } else {
        NFCLOG_E("nci_nfcee_discover failed: 0x%02X", ret);
    }
    RELEASE_EM_LOCK();
    // 在锁范围外enable ee
    if (ret == NCI_STATUS_OK) {
        enable_ee_unsupported_hci();
    }

    return ret == NCI_STATUS_OK;
}

/**
 * @brief 设置EE的power and link control
 *
 * @param enable 设置开启、关闭
 */
void nfa_ee_set_power_and_link_ctrl(bool enable) {
    NFCLOG_D("enter");
    GET_EM_LOCK_OR_RETURN();
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
    } else {
        tNCI_EE_POWER_AND_LINK_CFG cfg = NCI_EE_POWER_AND_LINK_CFG_NFCC_DECIDE;
        if (enable) {
            // TODO: 使用config中配置的值
            cfg = NCI_EE_POWER_AND_LINK_CFG_ALL_ALWAYS_ON;
        }
        uint8_t ee = nfc_config_get()->vendor_cf.offhost_route_ese.data[0];
        nci_nfcee_power_and_link_cntrl(ee, cfg);
    }
    RELEASE_EM_LOCK();
}

/**
 * @brief 获取处于激活状态的EE
 *
 * @param[out] buff 用于接受nfcee列表的内存区域
 * @param[inout] len 表示输入buff的大小，函数执行后返回的列表的大小
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_ee_get_active_nfcee_list(uint8_t* buff, uint8_t* len) {
    NFCLOG_D("enter");
    if (buff == NULL || len == NULL) {
        NFCLOG_E("invalid params");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    GET_EM_LOCK();
    tNCI_STATUS ret = NCI_STATUS_OK;
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
        goto unlock;
    }
    uint8_t active_num = 0;
    for (int i = 0; i < s_ee_mod.cur_ee_num; i++) {
        if (s_ee_mod.nfcees[i].status == NCI_NFCEE_ENABLED) {
            if (*len > active_num) {
                buff[active_num] = s_ee_mod.nfcees[i].nfcee_id;
            } else {
                NFCLOG_E("buffer len is not enough");
                ret = NCI_STATUS_EXT_COPY_FAILED;
                goto unlock;
            }
            active_num++;
        }
    }
    NFCLOG_D("get %d active nfcees", active_num);
    *len = active_num;
unlock:
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 获取EE的实际名称
 *
 * @param[in] ee 传入的EE的id
 *
 * @return 成功返回EE对应的名称，失败返回NULL
 */
const char* nfa_ee_get_nfcee_name(uint8_t ee) {
    NFCLOG_D("enter, ee: 0x%02X", ee);
    const char* ese_name[] = {EE_NAME_ESE1, EE_NAME_ESE2};
    uint8_t ese_name_size = sizeof(ese_name) / sizeof(const char*);
    const char* sim_name[] = {EE_NAME_SIM1, EE_NAME_SIM2};
    uint8_t sim_name_size = sizeof(sim_name) / sizeof(const char*);
    const tNFC_CF* cf = nfc_config_get();
    for (uint8_t i = 0; i < cf->vendor_cf.offhost_route_ese.len && i < ese_name_size; i++) {
        if (ee == cf->vendor_cf.offhost_route_ese.data[i]) {
            return ese_name[i];
        }
    }
    for (uint8_t i = 0; i < cf->vendor_cf.offhost_route_uicc.len && i < sim_name_size; i++) {
        if (ee == cf->vendor_cf.offhost_route_uicc.data[i]) {
            return sim_name[i];
        }
    }
    return NULL;
}

/**
 * @brief 获取EE的实际id
 *
 * @param[in] type 传入的EE的类型
 *
 * @return 成功返回EE对应的id，失败返回无效值FF
 */
uint8_t nfa_ee_get_nfcee_id(tNCI_EE_TYPE type) {
    uint8_t ee_id = 0xFF;
    uint8_t ese_num = nfc_config_get()->vendor_cf.offhost_route_ese.len;
    uint8_t sim_num = nfc_config_get()->vendor_cf.offhost_route_uicc.len;
    switch (type) {
        case NCI_NFCEE_ESE1:
            if (ese_num > 0) {
                ee_id = nfc_config_get()->vendor_cf.offhost_route_ese.data[0];
            }
            break;
        case NCI_NFCEE_SIM1:
            if (sim_num > 0) {
                ee_id = nfc_config_get()->vendor_cf.offhost_route_uicc.data[0];
            }
            break;
        case NCI_NFCEE_SIM2:
            if (sim_num > 1) {
                ee_id = nfc_config_get()->vendor_cf.offhost_route_uicc.data[1];
            }
            break;
        default:
            NFCLOG_E("invalid ee type: %d", type);
            break;
    }
    return ee_id;
}

/**
 * @brief 获取EE模块中记录的所有NFCEE的信息，不包括DH
 *
 * @param ee_num 传入指针，函数执行成功后返回的实际nfcee信息的数量
 * @param infos  传入指针，函数执行成功后返回的实际nfcee信息
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS ee_get_info(uint8_t* ee_num, tNCI_EE_INFO* infos) {
    NFCLOG_D("em_state:%d, cur_ee_num=%d", s_ee_mod.em_state, s_ee_mod.cur_ee_num);
    if (ee_num == NULL || infos == NULL) {
        NFCLOG_E("invalid params");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    GET_EM_LOCK();
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
        goto unlock;
    }
    *ee_num = s_ee_mod.cur_ee_num;
    for (int i = 0; i < s_ee_mod.cur_ee_num; i++) {
        infos[i].ee_id = s_ee_mod.nfcees[i].nfcee_id;
        infos[i].using_hci = s_ee_mod.nfcees[i].num_of_protocol == 0;
        infos[i].status = s_ee_mod.nfcees[i].status;
    }
    NFCLOG_D("num_ret = %d", *ee_num);
    ret = NCI_STATUS_OK;
unlock:
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 获取EE模块中记录的所有NFCEE的discovery requset信息
 *
 * @param req 传入指针，函数执行成功后返回所有NFCEE的discovery requset信息
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS ee_get_discovery_req(tNCI_EE_DISCOVER_REQ* req) {
    if (!req) {
        NFCLOG_E("invalid param");
    }
    GET_EM_LOCK();
    uint8_t num = 0;
    for (int i = 0; i < s_ee_mod.cur_ee_num; i++) {
        tNCI_NFCEE* ee = &s_ee_mod.nfcees[i];
        if (ee->status != NCI_NFCEE_ENABLED) {
            continue;
        }
        req->infos[num].ee_id = ee->nfcee_id;
        req->infos[num].la_protocol = ee->la_protocol;
        req->infos[num].lb_protocol = ee->lb_protocol;
        req->infos[num].lf_protocol = ee->lf_protocol;
        num++;
    }
    req->ee_num = num;
    RELEASE_EM_LOCK();
    return NCI_STATUS_OK;
}

/**
 * @brief 激活或者去激活EE
 *
 * @param ee_id 目标EE的id
 * @param mode  期望设置的ee状态
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS ee_mode_set(uint8_t ee_id, tNCI_EE_MODE mode) {
    NFCLOG_D("ee mode setting, em_state:%d, ee_id:0x%X, mode:%d", s_ee_mod.em_state, ee_id, mode);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    tNCI_NFCEE* ee = get_ee_by_id(ee_id);
    if (!ee) {
        NFCLOG_E("invalid ee id:0x%X", ee_id);
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    GET_EM_LOCK();
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        RELEASE_EM_LOCK();
        return NCI_STATUS_EXT_STATE_INCORRECT;
    }
    RELEASE_EM_LOCK();
    ret = nci_nfcee_mode_set(ee_id, mode);
    if (ret == NCI_STATUS_OK) {
        ee->status = (mode == NCI_NFCEE_MODE_ENABLE)? NCI_NFCEE_ENABLED: NCI_NFCEE_DISABLED;
    } else if (ret == NCI_STATUS_NFCEE_TRANSMISSION_ERROR) {
        ee->status = NCI_NFCEE_UNRESPONSIVE;
    } else {
        NFCLOG_W("set nfcee 0x%02X mode %d failed, ret=%d", ee->nfcee_id, mode, ret);
    }
    return ret;
}

/**
 * @brief 设置EE的power and link状态
 *
 * @param ee_id 目标EE的id
 * @param cfg   期望设置的power and link状态
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS ee_power_and_link_ctrl(uint8_t ee_id, tNCI_EE_POWER_AND_LINK_CFG cfg) {
    NFCLOG_D("ee power&link setting, em_state:%d, ee_id:0x%X, config:%d", s_ee_mod.em_state, ee_id, cfg);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    if (!get_ee_by_id(ee_id)) {
        NFCLOG_E("invalid ee id:0x%X", ee_id);
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    GET_EM_LOCK();
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        RELEASE_EM_LOCK();
        return NCI_STATUS_EXT_STATE_INCORRECT;
    }
    RELEASE_EM_LOCK();
    ret = nci_nfcee_power_and_link_cntrl(ee_id, cfg);
    return ret;
}

/**
 * @brief 向NFCEE管理模块中注册ee模块事件回调，收到EE管理模块在收到ee模块事件后会触发回调给调用方
 *
 * @param cb 调用方设置的回调，用于接收来自ee管理模块的事件和数据
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS ee_register_cback(tNCI_EE_CBACK cb) {
    if (cb == NULL) {
        NFCLOG_E("invalid ee call back!");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    GET_EM_LOCK();
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
        goto unlock;
    }
    for(int i = 0; i < NCI_MAX_NFCEE_CBACKS; i++) {
        if (s_ee_mod.p_em_cbacks[i] == cb) {
            ret = NCI_STATUS_OK;
            NFCLOG_D("ee cback already registered.");
            break;
        } else if (s_ee_mod.p_em_cbacks[i] == NULL) {
            s_ee_mod.p_em_cbacks[i] = cb;
            ret = NCI_STATUS_OK;
            NFCLOG_D("ee register cback success.");
            break;
        } else if (NCI_MAX_NFCEE_CBACKS - 1 == i) {
            NFCLOG_W("em cback were all used!.");
        }
    }
unlock:
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 向NFCEE管理模块取消注册ee模块事件回调
 *
 * @param cb 调用方先前调用ee_register_cback设置的回调
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS ee_deregister_cback(tNCI_EE_CBACK cb) {
    if (cb == NULL) {
        NFCLOG_E("invalid ee call back!");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    GET_EM_LOCK();
    tNCI_STATUS ret = NCI_STATUS_EXT_NOT_FOUND;
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
        goto unlock;
    }
    for(int i = 0; i < NCI_MAX_NFCEE_CBACKS; i++) {
        if (s_ee_mod.p_em_cbacks[i] == cb) {
            s_ee_mod.p_em_cbacks[i] = NULL;
            ret = NCI_STATUS_OK;
            NFCLOG_D("ee deregister cback success.");
            break;
        }
    }
unlock:
    RELEASE_EM_LOCK();
    return ret;
}

#if IS_FEATURE_ON(NCI_FEATURE_ROUTING)
/**
 * @brief 路由表元素释放函数
 */
static void cleanup_routing_entry(tQUEUE_ID id, tQUEUE_TAG tag, void* data) {
    (void) id;
    (void) tag;
    if (data) {
        osi_free(data);
    }
}

/**
 * @brief 从路由表中移除指定路由表元素
 *
 * @param tag 路由项的类型
 * @param data 路由项的数据
 * @param data_len 数据长度
 *
 * @return 移除成功返回true，否则返回false
 */
static bool remove_routing_entry(tQUEUE_TAG tag, void *data, uint8_t data_len) {
    // em状态机不在enable状态，返回
    if (!check_em_state_unlock(NCI_EE_MODULE_ENABLE_DONE)) {
        return false;
    }
    tQUEUE_NODE *curr = s_routing_table.root;
    while (curr) {
        if (curr->tag != tag) {
            curr = curr->next;
            continue;
        }
        tNCI_RF_ROUTING_ENTRY *entry = (tNCI_RF_ROUTING_ENTRY*) curr->data;
        if (!entry || entry->entry_len != data_len) {
            curr = curr->next;
            continue;
        }
        if (data_len == 0 || 0 == memcmp(data, &entry->entry_data, data_len)) {
            tNCI_RF_ROUTING_ENTRY *_entry = pq_remove(&s_routing_table, curr->id);
            osi_free(_entry);
            return true;
        }
        curr = curr->next;
    }
    return false;
}

/**
 * @brief 查找路由表中的指定路由表元素
 *
 * @note 查找tag和data匹配的路由表项
 *
 * @param tag 路由项的类型
 * @param data 路由项的数据
 * @param data_len 数据长度
 *
 * @return 找到返回路由表元素指针，否则返回NULL
 */
static tNCI_RF_ROUTING_ENTRY* find_routing_entry(tQUEUE_TAG tag, void *data, uint8_t data_len) {
    tQUEUE_NODE *curr = s_routing_table.root;
    while (curr) {
        if (curr->tag != tag) {
            curr = curr->next;
            continue;
        }
        tNCI_RF_ROUTING_ENTRY *entry = (tNCI_RF_ROUTING_ENTRY*) curr->data;
        if (!entry || entry->entry_len != data_len) {
            curr = curr->next;
            continue;
        }
        if (data_len == 0) {
            return entry;
        }
        if (data && 0 == memcmp(data, &entry->entry_data, data_len)) {
            return entry;
        }
        curr = curr->next;
    }
    return NULL;
}

/**
 * @brief 将路由表项插入到路由表中，或是更新路由表中的路由项
 *
 * @note 当路由表中存在相同tag和data的路由项时，更新路由表中的路由项，否则插入新的路由项
 *
 * @param tag 路由项的类型
 * @param entry 要插入或是更新的路由表项
 *
 * @return 插入或更新成功返回NCI_STATUS_OK，否则返回NCI_STATUS_EXT_FAILED
 */
static tNCI_STATUS create_or_update_routing_entry(tQUEUE_TAG tag, tNCI_RF_ROUTING_ENTRY *entry) {
    // em状态机不在enable状态，返回
    if (!check_em_state_unlock(NCI_EE_MODULE_ENABLE_DONE)) {
        return NCI_STATUS_EXT_STATE_INCORRECT;
    }
    // ee不是enable状态，返回
    if (!check_ee_enabled_unlock(entry->nfcee_id)) {
        return NCI_STATUS_EXT_STATE_INCORRECT;
    }
    tNCI_RF_ROUTING_ENTRY *table_entry = find_routing_entry(tag, &entry->entry_data, entry->entry_len);
    if (table_entry) {
        // 此元素已在路由表中，直接更新
        NFCLOG_D("This route entry %d already in talbe, override it.", tag);
        return osi_memcpy_s(table_entry, sizeof(tNCI_RF_ROUTING_ENTRY), entry, sizeof(tNCI_RF_ROUTING_ENTRY)) ? NCI_STATUS_OK : NCI_STATUS_EXT_COPY_FAILED;
    }
    // 此元素未添加过，创建新的路由表元素
    // 注意，这里分配的table_entry，在正常加入到s_routing_table后，由队列的cleanup函数清理，在此函数中的正常流程无需要清理
    table_entry = (tNCI_RF_ROUTING_ENTRY*) osi_calloc(sizeof(tNCI_RF_ROUTING_ENTRY));
    if (!table_entry) {
        return NCI_STATUS_EXT_ALLOC_FAILED;
    }
    if (!osi_memcpy_s(table_entry, sizeof(tNCI_RF_ROUTING_ENTRY), entry, sizeof(tNCI_RF_ROUTING_ENTRY))) {
        osi_free(table_entry);
        return NCI_STATUS_EXT_COPY_FAILED;
    }
#if IS_FEATURE_ON(NCI_FEATURE_EE_DH)
    if (entry->nfcee_id == NCI_DH_NFCEE_ID && s_ee_mod.secure_nfc_enabled) {
        NFCLOG_I("DH is secure, set power state to 0x%X", entry->power_state & NCI_SECURE_NFC_POWER_STATE_MASK);
        table_entry->power_state &= NCI_SECURE_NFC_POWER_STATE_MASK;
    }
#endif // IS_FEATURE_ON(NCI_FEATURE_EE_DH)
    // 按照AID - APDU PATTERN - SYSTEM CODE - PROTOCOL - TECH的顺序添加到路由表
    tQUEUE_PRIORITY priority = ROUTE_PRIORITY_AID;
    if (tag == NCI_ROUTING_ENTRY_AID && !entry->entry_len) {
        priority = ROUTE_PRIORITY_EMPTY_AID;
    } else if (tag == NCI_ROUTING_ENTRY_APDU_PATTERN) {
        priority = ROUTE_PRIORITY_APDU_PATTERN;
    } else if (tag == NCI_ROUTING_ENTRY_SYSTEMCODE) {
        priority = ROUTE_PRIORITY_SYS_CODE;
    } else if (tag == NCI_ROUTING_ENTRY_PROTOCOL) {
        priority = ROUTE_PRIORITY_PROTOCOL;
    } else if (tag == NCI_ROUTING_ENTRY_TECH) {
        if (entry->entry_data.tech == NCI_RF_TECH_A) {
            priority = ROUTE_PRIORITY_TECH_A;
        } else if (entry->entry_data.tech == NCI_RF_TECH_B) {
            priority = ROUTE_PRIORITY_TECH_B;
        } else if (entry->entry_data.tech == NCI_RF_TECH_F) {
            priority = ROUTE_PRIORITY_TECH_F;
        }
    }
    // 相同的EE存放在一起
    priority |= entry->nfcee_id;
    // 添加到路由表中
    if (!pq_enqueue(&s_routing_table, table_entry, priority, tag, NULL)) {
        osi_free(table_entry);
        return NCI_STATUS_EXT_QUEUE_ERROR;
    }
    return NCI_STATUS_OK;
}

/**
 * @brief 向路由表中添加AID路由
 *
 * @note 如果同一个AID已经存在，则更新路由表中的AID路由
 *
 * @param ee_id 路由项所属的NFCEE ID
 * @param power_state 路由项的电源状态
 * @param aid AID，NULL表示AID*
 * @param aid_len AID长度
 *
 * @return 添加成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_add_aid(uint8_t ee_id, tNCI_EE_PWR_STATE power_state, uint8_t *aid, uint8_t aid_len, tNCI_AID_INFO aid_info) {
    NFCLOG_D("ee_id: 0x%02X, aid_len: %d, aid_info: 0x%02X, power_state: 0x%02X", ee_id, aid_len, aid_info, power_state);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    if (aid == NULL && aid_len != 0) {
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    GET_EM_LOCK();
    // empty aid的路由长度已经被算进fixed entry size，不受此处限制
    if (aid_len != 0 && s_ee_mod.cur_aid_rt_size + aid_len + NCI_LMRT_ENTRY_HEAD_LEN > s_ee_mod.max_aid_rt_size) {
        NFCLOG_E("Exceed MAX aid table size!");
        ret = NCI_STATUS_EXT_REJECTED;
        goto unlock;
    }
    tNCI_RF_ROUTING_ENTRY entry = {
        .qualifier_type = (aid_info & 0xF0) | NCI_ROUTING_ENTRY_AID,
        .nfcee_id = ee_id,
        .power_state = power_state,
        .entry_len = aid_len,
    };
    if (aid && aid_len > 0) {
        if (!osi_memcpy_s(entry.entry_data.aid, NCI_ROUTING_AID_MAX_SIZE, aid, aid_len)) {
            ret = NCI_STATUS_EXT_COPY_FAILED;
            goto unlock;
        }
    }
    ret = create_or_update_routing_entry(NCI_ROUTING_ENTRY_AID, &entry);
    // empty aid的路由长度已经被算进fixed entry size，此处不用再计算
    if (ret == NCI_STATUS_OK && aid_len != 0) {
        s_ee_mod.cur_aid_rt_size += aid_len + NCI_LMRT_ENTRY_HEAD_LEN;
    }
unlock:
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 删除路由表中的AID路由
 *
 * @param aid AID，NULL表示AID*
 * @param aid_len AID长度
 *
 * @return 删除成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_remove_aid(uint8_t *aid, uint8_t aid_len) {
    NFCLOG_D("aid_len: %d", aid_len);
    if (aid == NULL && aid_len != 0) {
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    tNCI_STATUS ret = NCI_STATUS_OK;
    GET_EM_LOCK();
    // empty aid的路由长度已经被算进fixed entry size，此处不用再计算
    if (remove_routing_entry(NCI_ROUTING_ENTRY_AID, aid, aid_len) && aid_len != 0) {
        s_ee_mod.cur_aid_rt_size -= aid_len + NCI_LMRT_ENTRY_HEAD_LEN;
    }
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 添加SystemCode类型路由
 *
 * @param ee_id 路由项所属的NFCEE ID
 * @param power_state 路由项的电源状态
 * @param system_code SystemCode编码，高字节在前
 *
 * @return 添加成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_add_sys_code(uint8_t ee_id, tNCI_EE_PWR_STATE power_state, uint16_t system_code) {
    NFCLOG_D("ee_id: 0x%02X, power_state: 0x%02X, system_code: 0x%X", ee_id, power_state, system_code);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    GET_EM_LOCK();
    tNCI_RF_ROUTING_ENTRY entry = {
        .qualifier_type = NCI_ROUTING_ENTRY_SYSTEMCODE,
        .nfcee_id = ee_id,
        .power_state = power_state,
        .entry_len = 2,
        .entry_data.sys_code = {system_code >> 8, system_code & 0xFF}
    };

    ret = create_or_update_routing_entry(NCI_ROUTING_ENTRY_SYSTEMCODE, &entry);
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 移除SystemCode类型路由
 *
 * @param system_code 需要移除的SystemCode编码，高字节在前
 *
 * @return 删除成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_remove_sys_code(uint16_t system_code) {
    uint8_t sys_code[2] = {system_code >> 8, system_code & 0xFF};
    NFCLOG_D("system_code: 0X%02X", system_code);
    GET_EM_LOCK();
    remove_routing_entry(NCI_ROUTING_ENTRY_SYSTEMCODE, sys_code, 2);
    RELEASE_EM_LOCK();
    return NCI_STATUS_OK;
}

/**
 * @brief 添加Tech类型路由
 *
 * @param ee_id 路由项所属的NFCEE ID
 * @param power_state 路由项的电源状态
 * @param tech Tech类型
 *
 * @return 添加成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_add_tech(uint8_t ee_id, tNCI_EE_PWR_STATE power_state, tNCI_RF_TECH tech) {
    NFCLOG_D("ee_id: 0x%02X, power_state: 0x%02X, tech: 0x%X", ee_id, power_state, tech);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    GET_EM_LOCK();
    tNCI_RF_ROUTING_ENTRY entry = {
        .qualifier_type = NCI_ROUTING_ENTRY_TECH,
        .nfcee_id = ee_id,
        .power_state = power_state,
        .entry_len = 1,
        .entry_data.tech = tech
    };

    ret = create_or_update_routing_entry(NCI_ROUTING_ENTRY_TECH, &entry);
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 移除Tech类型路由
 *
 * @param tech 需要移除的Tech类型
 *
 * @return 删除成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_remove_tech(tNCI_RF_TECH tech) {
    NFCLOG_D("tech: 0X%02X", tech);
    GET_EM_LOCK();
    remove_routing_entry(NCI_ROUTING_ENTRY_TECH, &tech, 1);
    RELEASE_EM_LOCK();
    return NCI_STATUS_OK;
}

/**
 * @brief 添加Protocol类型路由
 *
 * @param ee_id 路由项所属的NFCEE ID
 * @param power_state 路由项的电源状态
 * @param protocol Protocol类型
 *
 * @return 添加成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_add_protocol(uint8_t ee_id, tNCI_EE_PWR_STATE power_state, tNCI_RF_PROTOCOL protocol) {
    NFCLOG_D("ee_id: 0x%02X, power_state: 0x%02X, protocol: 0x%X", ee_id, power_state, protocol);
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    GET_EM_LOCK();
    tNCI_RF_ROUTING_ENTRY entry = {
        .qualifier_type = NCI_ROUTING_ENTRY_PROTOCOL,
        .nfcee_id = ee_id,
        .power_state = power_state,
        .entry_len = 1,
        .entry_data.protocol = protocol
    };

    ret = create_or_update_routing_entry(NCI_ROUTING_ENTRY_PROTOCOL, &entry);
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 移除Protocol类型路由
 *
 * @param protocol 需要移除的Protocol类型
 *
 * @return 删除成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_remove_protocol(tNCI_RF_PROTOCOL protocol) {
    NFCLOG_D("protocol: 0X%02X", protocol);
    tNCI_STATUS ret = NCI_STATUS_OK;
    GET_EM_LOCK();
    remove_routing_entry(NCI_ROUTING_ENTRY_PROTOCOL, &protocol, 1);
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 清除指定类型的所有路由
 *
 * @param type 路由类型
 *
 * @return 清除成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_clear(tNCI_ROUTING_ENTRY_TYPE type) {
    tNCI_STATUS ret = NCI_STATUS_OK;
    NFCLOG_D("clear route type: %d", type);
    GET_EM_LOCK();
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
    } else {
        pq_remove_all(&s_routing_table, type, true);
        if (type == NCI_ROUTING_ENTRY_AID) {
            s_ee_mod.cur_aid_rt_size = 0;
        }
    }
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 清除所有路由
 *
 * @return 清除成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_clear_all() {
    NFCLOG_D("enter.");
    tNCI_STATUS ret = NCI_STATUS_OK;
    GET_EM_LOCK();
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
    } else {
        pq_clear(&s_routing_table, true);
    }
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 更新路由表，将路由表中的路由项发送给NFCC
 *
 * @return 更新成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_commit() {
    NFCLOG_D("route commiting");
    tNCI_RF_ROUTING_ENTRY *entries = osi_calloc(sizeof(tNCI_RF_ROUTING_ENTRY) * s_routing_table.size);
    if (!entries) {
        NFCLOG_E("alloc entries failed!");
        return NCI_STATUS_EXT_ALLOC_FAILED;
    }
    tNCI_STATUS ret = NCI_STATUS_EXT_FAILED;
    GET_EM_LOCK();
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
        goto cleanup;
    }

    tNCI_RF_ROUTING_ENTRY *p_entries = entries;
    tQUEUE_NODE *curr = s_routing_table.root;
    tNCI_RF_ROUTING_ENTRY *entries_to_send = entries;
    uint16_t cur_entries_size = 0;
    uint8_t cur_entries_count = 0;
    while (curr) {
        NFCLOG_D("cur_entries_size=%d, cur_entries_count=%d", cur_entries_size, cur_entries_count);
        tNCI_RF_ROUTING_ENTRY *entry = (tNCI_RF_ROUTING_ENTRY*) curr->data;
        if (!osi_memcpy_s(p_entries, sizeof(tNCI_RF_ROUTING_ENTRY), entry, sizeof(tNCI_RF_ROUTING_ENTRY))) {
            goto cleanup;
        }
        // 如果此条entry导致单条路由表设置指令超过最大值，则把之前的先设置到NFCC, 并把待发送entries的起点设为该条
        if (cur_entries_size + entry->entry_len + NCI_LMRT_ENTRY_HEAD_LEN > NCI_SET_LMRT_MAX_ENTRY_SIZE) {
            ret = nci_rf_set_listen_mode_routing(entries_to_send, cur_entries_count, true);
            if (ret != NCI_STATUS_OK) {
                NFCLOG_E("set lmrt failed!");
                goto cleanup;
            }
            entries_to_send = p_entries;
            cur_entries_size = 0;
            cur_entries_count = 0;
        }
        cur_entries_size += p_entries->entry_len + NCI_LMRT_ENTRY_HEAD_LEN;
        cur_entries_count++;
        p_entries++;
        curr = curr->next;
    }

    ret = nci_rf_set_listen_mode_routing(entries_to_send, cur_entries_count, false);
cleanup:
    if (entries) {
        osi_free(entries);
    }
    RELEASE_EM_LOCK();
    return ret;
}
/**
 * @brief 获取路由表容量大小
 *
 * @return 返回路由表容量大小
 */
uint16_t nfa_ee_get_lmrt_max_size() {
    GET_EM_LOCK_OR_RETURN(0);
    uint16_t ret = 0;
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
    } else {
        ret = s_ee_mod.max_rt_size;
    }
    RELEASE_EM_LOCK();
    return ret;
}
/**
 * @brief 获取路由表中预留给Aid路由部分的大小
 *
 * @return 返回对应错误码路由表中预留给Aid路由部分的大小
 */
uint16_t nfa_ee_get_aid_table_size() {
    GET_EM_LOCK_OR_RETURN(0);
    uint16_t ret = 0;
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
    } else {
        ret = s_ee_mod.max_aid_rt_size;
    }
    RELEASE_EM_LOCK();
    return ret;
}
/**
 * @brief 获取当前路由表
 *
 * @param buff 传入用于获取路由表的buffer
 * @param len 传入用于获取路由表的buffer的大小, 成功时修改为路由表的准确大小
 *
 * @return 成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS nfa_ee_get_lmrt(uint8_t* buff, uint16_t *len) {
    if (!buff || !len) {
        NFCLOG_E("invalid param");
        return NCI_STATUS_EXT_INVALID_PARAM;
    }
    tNCI_STATUS ret = NCI_STATUS_OK;
    GET_EM_LOCK();
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
        goto unlock;
    }
    tQUEUE_NODE *curr = s_routing_table.root;
    uint16_t lmrt_size = 0;
    while (curr) {
        tNCI_RF_ROUTING_ENTRY *entry = (tNCI_RF_ROUTING_ENTRY*) curr->data;
        lmrt_size += entry->entry_len + NCI_LMRT_ENTRY_HEAD_LEN;
        curr = curr->next;
    }
    NFCLOG_D("lmrt size: %d", lmrt_size);
    if (*len < lmrt_size) {
        NFCLOG_E("Buffer size too small");
        ret = NCI_STATUS_EXT_INVALID_PARAM;
        goto unlock;
    }
    uint8_t* lmrt = osi_calloc(lmrt_size);
    uint8_t offet = 0;
    if (!lmrt) {
        NFCLOG_E("calloc lmrt failed!");
        ret = NCI_STATUS_EXT_ALLOC_FAILED;
        goto unlock;
    }
    // 重新指向root
    curr = s_routing_table.root;
    while (curr && (offet < lmrt_size)) {
        tNCI_RF_ROUTING_ENTRY *entry = (tNCI_RF_ROUTING_ENTRY*) curr->data;
        *(lmrt + offet++) = entry->qualifier_type;
        *(lmrt + offet++) = entry->entry_len + 2;
        *(lmrt + offet++) = entry->nfcee_id;
        *(lmrt + offet++) = entry->power_state;
        uint8_t *entry_data = (uint8_t*) &entry->entry_data;
        if (!osi_memcpy_s(lmrt + offet, lmrt_size - offet, entry_data, entry->entry_len)) {
            NFCLOG_E("copy entry_data failed");
            ret = NCI_STATUS_EXT_COPY_FAILED;
            goto cleanup;
        }
        offet += entry->entry_len;
        curr = curr->next;
    }
    if (!osi_memcpy_s(buff, *len, lmrt, lmrt_size)) {
        NFCLOG_E("copy lmrt failed");
        ret = NCI_STATUS_EXT_COPY_FAILED;
        goto cleanup;
    }
    // 拷贝lmrt成功后，修改len为实际的buffer长度
    *len = lmrt_size;
cleanup:
    osi_free(lmrt);
unlock:
    RELEASE_EM_LOCK();
    return ret;
}
#if IS_FEATURE_ON(NCI_FEATURE_EE_DH)
/**
 * @brief 设置secure NFC状态
 *
 * @note secure NFC状态下，只有screen on unlocked状态下的DH才能被路由到
 * @note 不影响Offhost的路由
 * @note 需要commit routing后生效
 * @param enable 是否开启secure NFC
 *
 * @return 设置成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS ee_route_set_secure_nfc(bool enable) {
    GET_EM_LOCK();
    s_ee_mod.secure_nfc_enabled = enable;
    NFCLOG_D("set secure nfc %s", enable ? "enabled" : "disabled");
    RELEASE_EM_LOCK();
    return NCI_STATUS_OK;
}
#endif // IS_FEATURE_ON(NCI_FEATURE_EE_DH)

#endif // IS_FEATURE_ON(NCI_FEATURE_ROUTING)

/**
 * @brief 获取EE的数据通道号
 *
 * @param[in] ee_id 传入的EE的ID
 *
 * @return 成功返回对应EE的数据通道号，否则返回0
 */
uint8_t nfa_ee_get_channel_id(uint8_t ee_id) {
    GET_EM_LOCK_OR_RETURN(0);
    uint8_t conn_id = 0;
    tNCI_NFCEE* ee = get_ee_by_id(ee_id);
    if (!ee) {
        NFCLOG_E("invalid ee %d!", ee_id);
    } else {
        conn_id = ee->conn_id;
    }
    RELEASE_EM_LOCK();
    return conn_id;
}

/**
 * @brief 打开与选中的EE之间的数据通道
 *
 * @param[in] ee_id 传入的EE的ID
 * @param[in] interface 打开通道的目标接口
 *
 * @return 成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS nfa_ee_open_channel(uint8_t ee_id, tNCI_EE_PROTOCOLS interface) {
    GET_EM_LOCK();
    tNCI_STATUS ret = NCI_STATUS_FAILED;
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
        goto unlock;
    }
    tNCI_NFCEE* ee = get_ee_by_id(ee_id);
    if (!ee || (ee->status != NCI_NFCEE_ENABLED)) {
        NFCLOG_E("ee 0x%02X is not enabled!", ee_id);
        goto unlock;
    }
    // 如果channel已经打开，则不再重复打开
    if (ee->conn_id) {
        NFCLOG_I("channel %d on ee 0x%02X is opened.", ee->conn_id, ee_id);
        ret = NCI_STATUS_EXT_ALREADY_OPENED;
        goto unlock;
    }
    uint8_t conn_id = 0;
    ret = nci_data_open_nfcee_dynamic_channel(ee_id, interface, &conn_id);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("ee 0x%02X open type %d channel failed!", ee_id, interface);
    } else {
        ee->conn_id = conn_id;
    }
unlock:
    RELEASE_EM_LOCK();
    return ret;
}

/**
 * @brief 关闭与选中的EE之间的数据通道
 *
 * @param[in] ee_id 传入的EE的ID
 *
 * @return 成功返回NCI_STATUS_OK，否则返回对应错误码
 */
tNCI_STATUS nfa_ee_close_channel(uint8_t ee_id) {
    GET_EM_LOCK();
    tNCI_STATUS ret = NCI_STATUS_FAILED;
    if (s_ee_mod.em_state != NCI_EE_MODULE_ENABLE_DONE) {
        NFCLOG_E("bad em state: %d", s_ee_mod.em_state);
        ret = NCI_STATUS_EXT_STATE_INCORRECT;
        goto unlock;
    }
    tNCI_NFCEE* ee = get_ee_by_id(ee_id);
    if (!ee || !ee->conn_id) {
        NFCLOG_E("invalid ee %d!", ee_id);
        goto unlock;
    }
    ret = nci_data_channel_close(ee->conn_id);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("ee 0x%02X close channel failed!", ee_id);
    } else {
        ee->conn_id = 0;
    }
unlock:
    RELEASE_EM_LOCK();
    return ret;
}

static void init_extern_ee_module() {
    uint8_t num = sizeof(s_ext_ee) / sizeof(tNCI_EXTERN_EE*);
    if (!num) {
        NFCLOG_D("No extern EE.");
        return;
    }
    for (int i = 0; i < num; i++) {
        if (check_ee_enabled_unlock(s_ext_ee[i]->id)) {
            s_ext_ee[i]->init();
        } else {
            NFCLOG_W("Ext EE 0x%2X is not enabled.", s_ext_ee[i]->id);
        }
    }
}

static void deinit_extern_ee_module() {
    uint8_t num = sizeof(s_ext_ee) / sizeof(tNCI_EXTERN_EE*);
    if (!num) {
        NFCLOG_D("No extern EE.");
        return;
    }
    for (int i = 0; i < num; i++) {
        s_ext_ee[i]->deinit();
    }
}

/**
 * @brief NFCEE管理模块异步事件处理完成后，清理参数
 */
static void ee_evt_cleaner(uint32_t what, uint32_t arg1, uint64_t arg2, void* args) {
    (void) arg1;
    (void) arg2;
    NFCLOG_D("em_state:%d, evt:%d, clear args", s_ee_mod.em_state, what);
    if(args) {
        osi_free(args);
    }
}

/**
 * @brief NFCEE管理模块异步事件处理函数
 */
static bool ee_evt_handler(uint32_t what, uint32_t arg1, uint64_t arg2, void* args) {
    NFCLOG_D("em_state:%d, evt:%d, arg1: 0x%04X, handle start...",
              s_ee_mod.em_state, what, arg1);
    bool act = false;
    GET_EM_LOCK();
    switch (s_ee_mod.em_state) {
        case NCI_EE_MODULE_ENABLE_DONE:
            act = true;
            break;
        default:
            NFCLOG_D("bad em state.");
            break;
    }
    RELEASE_EM_LOCK();
    if (!act) {
        NFCLOG_D("no need to take action.");
        return false;
    }
    tNCI_EE_EVT_DATA data = {0};
    tNCI_NFCEE* ee = NULL;
    switch (what) {
        case NCI_TASK_EVT_EE_STATUS_NTF:
            ee = get_ee_by_id(arg1);
            if (!ee || ee->nfcee_id == NCI_DH_NFCEE_ID) {
                NFCLOG_W("invalid ee.");
                break;
            } else if (ee->status == NCI_NFCEE_ENABLED && arg2 == NCI_EE_STATUS_NTF_UNRECOVERABLE_ERROR) {
                NFCLOG_W("ee: 0x%02X turn into unrecoverable!", ee->nfcee_id);
                ee->status = NCI_NFCEE_UNRESPONSIVE;
                // 尝试恢复EE
                if (recover_ee()) {
                    report_em_event(NCI_EE_RECOVERY, &data);
                }
            }
            break;
        case NCI_TASK_EVT_EE_DISCOVERY_REQ_NTF:
            {
                tNCI_EE_DISCOVER_REQ_NTF req_ntf = {0};
                req_ntf.num = arg1;
                // 注意此处entrys的内存结构需要与传入数据保持一致
                osi_memcpy_s(req_ntf.entrys, sizeof(req_ntf.entrys), args, arg2);
                for (int i = 0; i < req_ntf.num; i++) {
                    bool add_req = (req_ntf.entrys[i].op == 0x00);
                    tNCI_RF_PROTOCOL protocol = add_req? req_ntf.entrys[i].protocol: NCI_RF_PROTOCOL_UNDETERMINED;
                    update_ee_discovery_req(req_ntf.entrys[i].nfcee_id, req_ntf.entrys[i].tech_mode, protocol);
                }
                ee_get_discovery_req(&data.discover_req);
                report_em_event(NCI_EE_DISCOVER_REQ_EVT, &data);
            }
            break;
        default:
            NFCLOG_D("Not support em msg:%d", what);
            break;
    }
    return true;
}

/**
 * @brief NFCEE管理模块初始化
 */
static tNCI_STATUS ee_init(const tNCI_MODULE_INIT_CFG *p_cfg) {
    if (osi_mutex_init_with_attr(&s_em_lock, true) != NFC_STATUS_OK) {
        NFCLOG_E("init mutex failed");
        return NCI_STATUS_EXT_FAILED;
    }

    GET_EM_LOCK();

    tNCI_STATUS ret = NCI_STATUS_OK;
#if IS_FEATURE_ON(NCI_FEATURE_ROUTING)
    if (!pq_init(&s_routing_table, pq_comp_min, cleanup_routing_entry)) {
        NFCLOG_E("Failed to init routing table");
        RELEASE_EM_LOCK();
        osi_mutex_deinit(&s_em_lock);
        return NCI_STATUS_EXT_FAILED;
    }
#endif // IS_FEATURE_ON(NCI_FEATURE_ROUTING)

    osi_memset_s(&s_ee_mod, sizeof(s_ee_mod), 0x00, sizeof(s_ee_mod));
    s_ee_mod.em_state = NCI_EE_MODULE_ENABLING;
    s_ee_mod.max_rt_size = p_cfg? p_cfg->init_resp.max_routing_table_size: 0x00;
    s_ee_mod.max_aid_rt_size = s_ee_mod.max_rt_size - ROUTE_FIXED_ENTRY_SIZE;
    NFCLOG_D("max_rt_size = %d, max_aid_rt_size = %d", s_ee_mod.max_rt_size, s_ee_mod.max_aid_rt_size);

#if IS_FEATURE_ON(NCI_FEATURE_EE_DH)
    s_ee_mod.nfcees[NCI_NFCEE_DH].nfcee_id = NCI_DH_NFCEE_ID;
    s_ee_mod.nfcees[NCI_NFCEE_DH].status = NCI_NFCEE_ENABLED;
    s_ee_mod.secure_nfc_enabled = false;
#endif

    nci_task_register(ee_evt_handler, ee_evt_cleaner, NCI_TASK_EVT_EE_GROUP);

    ret = nci_nfcee_discover(s_ee_mod.nfcees, &s_ee_mod.cur_ee_num);
    if (ret != NCI_STATUS_OK) {
        NFCLOG_E("nci_nfcee_discover failed!");
        RELEASE_EM_LOCK();
        osi_mutex_deinit(&s_em_lock);
        return ret;
    }

    NFCLOG_I("found nfcee count: %d", s_ee_mod.cur_ee_num);

    s_ee_mod.em_state = NCI_EE_MODULE_ENABLE_DONE;
    RELEASE_EM_LOCK();

    enable_ee_unsupported_hci();

    init_extern_ee_module();

    return ret;
}

/**
 * @brief NFCEE管理模块销毁
 */
static tNCI_STATUS ee_deinit(bool is_shutdown) {
    deinit_extern_ee_module();
    GET_EM_LOCK_OR_RETURN(NCI_STATUS_OK);
    for (uint8_t i = 0; i < s_ee_mod.cur_ee_num; ++i) {
        tNCI_NFCEE *nfcee = &s_ee_mod.nfcees[i];
        if (!is_shutdown && nfcee->status == NCI_NFCEE_ENABLED) {
            tNCI_STATUS ms_ret = nci_nfcee_mode_set(nfcee->nfcee_id, NCI_NFCEE_MODE_DISABLE);
            if (ms_ret == NCI_STATUS_OK) {
                nfcee->status = NCI_NFCEE_DISABLED;
            } else if (ms_ret == NCI_STATUS_NFCEE_TRANSMISSION_ERROR) {
                nfcee->status = NCI_NFCEE_UNRESPONSIVE;
            } else {
                NFCLOG_W("disable nfcee 0x%02X failed, ms_ret=%d", nfcee->nfcee_id, ms_ret);
            }
        }
    }

    s_ee_mod.em_state = NCI_EE_MODULE_DISABLED;
    osi_memset_s(&s_ee_mod, sizeof(s_ee_mod), 0, sizeof(s_ee_mod));
#if IS_FEATURE_ON(NCI_FEATURE_ROUTING)
    pq_deinit(&s_routing_table, true);
#endif // IS_FEATURE_ON(NCI_FEATURE_ROUTING)
    RELEASE_EM_LOCK();
    osi_mutex_deinit(&s_em_lock);
    return NCI_STATUS_OK;
}

/**
 * @brief EE管理模块dump函数
 */
static void ee_dump(int fd) {
    osi_dump(fd, "em state = %d", s_ee_mod.em_state);
    osi_dump(fd, "cur_ee_num = %d", s_ee_mod.cur_ee_num);
    for (int i =0; i < s_ee_mod.cur_ee_num; i++) {
        osi_dump(fd, "EE[%d]: 0x%02X, state: 0x%02X", i, s_ee_mod.nfcees[i].nfcee_id, s_ee_mod.nfcees[i].status);
        osi_dump(fd, "EE[%d] Type A REQ: %d", i, s_ee_mod.nfcees[i].la_protocol);
        osi_dump(fd, "EE[%d] Type B REQ: %d", i, s_ee_mod.nfcees[i].lb_protocol);
        osi_dump(fd, "EE[%d] Type F REQ: %d", i, s_ee_mod.nfcees[i].lf_protocol);
    }
    osi_dump(fd, "max_aid_rt_size = %d, cur_aid_rt_size = %d, max_rt_size = %d",
             s_ee_mod.max_aid_rt_size, s_ee_mod.cur_aid_rt_size, s_ee_mod.max_rt_size);
#if IS_FEATURE_ON(NCI_FEATURE_EE_DH)
    osi_dump(fd, "secure_nfc: %s", s_ee_mod.secure_nfc_enabled? "enabled": "disabled");
#endif // IS_FEATURE_ON(NCI_FEATURE_EE_DH)
}

/**
 * @brief NFCEE管理模块定义
 */
tNCI_MODULE g_nfcee_manager = {
    .name = "NFCEE_MANAGER",
    .state = NCI_MODULE_STATE_DISABLED,
    .init = ee_init,
    .deinit = ee_deinit,
    .dump = ee_dump,
};

#endif /* NCI_FEATURE_EE */
